package com.cosin.model.po;

import com.cosin.model.XMLObject.NodeXMLO;
import com.cosin.model.dto.NodeDTO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.*;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Objects;

@Node("node")
@Data
@Accessors(chain = true)
public class NodePO {

    @Id
    @GeneratedValue
    private Long id;

    @Property("nodeId")
    private Long nodeId;

    @Property("name")
    private String name;

    @Property("group")
    private String group;

    @Property("radius")
    private int radius;

    @Property("projectId")
    private int projectId;

    @Property("color")
    private String color;

    @Property("textSize")
    private String textSize;

    @Property("figure")
    private String figure;

    @Property("properties")
    private String propertiesAsString;

    @JsonManagedReference
    @Relationship(type = "relation", direction = Relationship.Direction.OUTGOING)
    private List<RelationPO> outgoingRelations;
    @JsonManagedReference
    @Relationship(type = "relation", direction = Relationship.Direction.INCOMING)
    private List<RelationPO> incomingRelations;

    public NodePO() {
    }

    public NodePO(NodeDTO nodeDTO) {
        if (nodeDTO != null) {
            BeanUtils.copyProperties(nodeDTO, this);
        }
        if (nodeDTO != null && nodeDTO.getProperties() != null) {
            setProperties(nodeDTO.getProperties());
        }
    }

    public NodePO(NodeXMLO nodeXMLO) {
        if (nodeXMLO != null) {
            BeanUtils.copyProperties(nodeXMLO, this);
        }
        if (nodeXMLO != null && nodeXMLO.getProperties() != null) {
            setProperties(nodeXMLO.getProperties());
        }
    }

    // 获取 properties 的 Map 形式
    public Map<String, String> getProperties() {
        if (propertiesAsString == null) {
            return new HashMap<>();
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(propertiesAsString, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return new HashMap<>();
        }
    }

    // 设置 properties，同时更新 propertiesAsString
    public void setProperties(Map<String, String> properties) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            this.propertiesAsString = objectMapper.writeValueAsString(properties);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            this.propertiesAsString = null;
        }
    }
    //ToString 函数
    @Override
    public String toString() {
        return "NodePO{" +
                "id=" + id +
                ", nodeId=" + nodeId +
                ", name='" + name + '\'' +
                ", group='" + group + '\'' +
                ", radius=" + radius +
                ", projectId=" + projectId +
                ", color='" + color + '\'' +
                ", textSize='" + textSize + '\'' +
                ", figure='" + figure + '\'' +
                ", propertiesAsString='" + propertiesAsString + '\'' +
                ", outgoingRelationsCount=" + (outgoingRelations != null ? outgoingRelations.size() : 0) +
                ", incomingRelationsCount=" + (incomingRelations != null ? incomingRelations.size() : 0) +
                '}';
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, nodeId, name, group, radius, projectId, color, textSize, figure, propertiesAsString);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        NodePO nodePO = (NodePO) obj;
        return Objects.equals(id, nodePO.id) &&
                Objects.equals(nodeId, nodePO.nodeId) &&
                Objects.equals(name, nodePO.name) &&
                Objects.equals(group, nodePO.group) &&
                Objects.equals(radius, nodePO.radius) &&
                Objects.equals(projectId, nodePO.projectId) &&
                Objects.equals(color, nodePO.color) &&
                Objects.equals(textSize, nodePO.textSize) &&
                Objects.equals(figure, nodePO.figure) &&
                Objects.equals(propertiesAsString, nodePO.propertiesAsString);
    }
}